package top.szhome.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.szhome.framework.core.tools.util.ObjectUtil;
import top.szhome.framework.starter.db.support.SimpleServiceImpl;
import top.szhome.system.convert.RoleConverter;
import top.szhome.system.dto.RoleDTO;
import top.szhome.system.entity.Role;
import top.szhome.system.entity.RoleMenu;
import top.szhome.system.mapper.RoleMapper;
import top.szhome.system.service.RoleMenuService;
import top.szhome.system.service.RoleService;
import top.szhome.system.vo.RoleVO;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 角色 服务实现
 *
 * @author 唐加利
 * @date 2023/07/31
 **/
@AllArgsConstructor
@Service
@Slf4j
public class RoleServiceImpl extends SimpleServiceImpl<RoleMapper, RoleConverter, RoleDTO, Role, RoleVO> implements RoleService {

    private final RoleMenuService roleMenuService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void grantMenus(List<Long> roleIds, List<Long> menuIds) {
        // 检索所有角色已分配菜单情况查询条件
        LambdaQueryWrapper<RoleMenu> wrapper = Wrappers.lambdaQuery(RoleMenu.class).in(RoleMenu::getRoleId, roleIds);

        // 全部取消分配，简化处理
        if(ObjectUtil.isEmpty(menuIds)){
            roleMenuService.remove(wrapper);
            return;
        }

        // 获取到每个角色已有的菜单集
        Map<Long, List<Long>> roleMenus = roleMenuService.getMenusOfRoles(roleIds);

        // 先转Set，提升检索效率
        Set<Long> menuSet = new HashSet<>(menuIds);

        // 待新增列表和待删除列表
        List<Long> allRemove = new LinkedList<>();
        List<RoleMenu> allAdd = new LinkedList<>();

        // 收集差异
        for(Long roleId : roleIds){
            List<Long> grantedList = roleMenus.get(roleId);

            // 尚未分配过菜单，简化处理
            if(ObjectUtil.isEmpty(grantedList)){
                allAdd.addAll(menuIds.stream().map(menuId -> new RoleMenu(roleId, menuId)).collect(Collectors.toList()));
                break;
            }

            // 角色已分配的菜单
            List<Long> granted = grantedList.stream().collect(Collectors.toList());

            // 已分配的菜单，且本次未分配，要删除
            List<Long> remove = granted.stream().filter(m -> !menuSet.contains(m)).collect(Collectors.toList());
            allRemove.addAll(remove);

            // 本次分配的菜单，且目前未分配，要新增
            List<RoleMenu> add = menuSet.stream().filter(id -> !granted.contains(id)).map(menuId -> new RoleMenu(roleId, menuId)).collect(Collectors.toList());
            allAdd.addAll(add);
        }

        // 批量删除、新增
        roleMenuService.removeBatchByIds(allRemove);
        roleMenuService.saveBatch(allAdd);
    }
}
